﻿using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using BooruViewer.Models;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;

namespace BooruViewer.Models
{
    public partial class Danbooru
    {
        [JsonProperty("id")]
        public long Id { get; set; }

        [JsonProperty("created_at")]
        public DateTimeOffset CreatedAt { get; set; }

        [JsonProperty("uploader_id")]
        public long UploaderId { get; set; }

        [JsonProperty("score")]
        public long Score { get; set; }

        [JsonProperty("source")]
        public string Source { get; set; }

        [JsonProperty("md5")]
        public string Md5 { get; set; }

        [JsonProperty("last_comment_bumped_at")]
        public object LastCommentBumpedAt { get; set; }

        [JsonProperty("rating")]
        public string Rating { get; set; }

        [JsonProperty("image_width")]
        public long ImageWidth { get; set; }

        [JsonProperty("image_height")]
        public long ImageHeight { get; set; }

        [JsonProperty("tag_string")]
        public string TagString { get; set; }

        [JsonProperty("is_note_locked")]
        public bool IsNoteLocked { get; set; }

        [JsonProperty("fav_count")]
        public long FavCount { get; set; }

        [JsonProperty("file_ext")]
        public string FileExt { get; set; }

        [JsonProperty("last_noted_at")]
        public DateTimeOffset? LastNotedAt { get; set; }

        [JsonProperty("is_rating_locked")]
        public bool IsRatingLocked { get; set; }

        [JsonProperty("parent_id")]
        public object ParentId { get; set; }

        [JsonProperty("has_children")]
        public bool HasChildren { get; set; }

        [JsonProperty("approver_id")]
        public long? ApproverId { get; set; }

        [JsonProperty("tag_count_general")]
        public long TagCountGeneral { get; set; }

        [JsonProperty("tag_count_artist")]
        public long TagCountArtist { get; set; }

        [JsonProperty("tag_count_character")]
        public long TagCountCharacter { get; set; }

        [JsonProperty("tag_count_copyright")]
        public long TagCountCopyright { get; set; }

        [JsonProperty("file_size")]
        public long FileSize { get; set; }

        [JsonProperty("is_status_locked")]
        public bool IsStatusLocked { get; set; }

        [JsonProperty("pool_string")]
        public string PoolString { get; set; }

        [JsonProperty("up_score")]
        public long UpScore { get; set; }

        [JsonProperty("down_score")]
        public long DownScore { get; set; }

        [JsonProperty("is_pending")]
        public bool IsPending { get; set; }

        [JsonProperty("is_flagged")]
        public bool IsFlagged { get; set; }

        [JsonProperty("is_deleted")]
        public bool IsDeleted { get; set; }

        [JsonProperty("tag_count")]
        public long TagCount { get; set; }

        [JsonProperty("updated_at")]
        public DateTimeOffset UpdatedAt { get; set; }

        [JsonProperty("is_banned")]
        public bool IsBanned { get; set; }

        [JsonProperty("pixiv_id")]
        public long? PixivId { get; set; }

        [JsonProperty("last_commented_at")]
        public object LastCommentedAt { get; set; }

        [JsonProperty("has_active_children")]
        public bool HasActiveChildren { get; set; }

        [JsonProperty("bit_flags")]
        public long BitFlags { get; set; }

        [JsonProperty("tag_count_meta")]
        public long TagCountMeta { get; set; }

        [JsonProperty("keeper_data")]
        public KeeperData KeeperData { get; set; }

        [JsonProperty("uploader_name")]
        public string UploaderName { get; set; }

        [JsonProperty("has_large")]
        public bool HasLarge { get; set; }

        [JsonProperty("has_visible_children")]
        public bool HasVisibleChildren { get; set; }

        [JsonProperty("children_ids")]
        public string ChildrenIds { get; set; }

        [JsonProperty("is_favorited")]
        public bool IsFavorited { get; set; }

        [JsonProperty("tag_string_general")]
        public string TagStringGeneral { get; set; }

        [JsonProperty("tag_string_character")]
        public string TagStringCharacter { get; set; }

        [JsonProperty("tag_string_copyright")]
        public string TagStringCopyright { get; set; }

        [JsonProperty("tag_string_artist")]
        public string TagStringArtist { get; set; }

        [JsonProperty("tag_string_meta")]
        public string TagStringMeta { get; set; }

        [JsonProperty("file_url")]
        public string FileUrl { get; set; }

        [JsonProperty("large_file_url")]
        public string LargeFileUrl { get; set; }

        [JsonProperty("preview_file_url")]
        public string PreviewFileUrl { get; set; }
    }

    public partial class KeeperData
    {
        [JsonProperty("uid")]
        public long? Uid { get; set; }
    }

    public partial class Danbooru
    {
        public static Danbooru[] FromJson(string json) => JsonConvert.DeserializeObject<Danbooru[]>(json, DanboConverter.Settings);
    }

    internal static class DanboConverter
    {
        public static readonly JsonSerializerSettings Settings = new JsonSerializerSettings
        {
            MetadataPropertyHandling = MetadataPropertyHandling.Ignore,
            DateParseHandling = DateParseHandling.None
        };
    }
    

    public static class DanboHelpers
    {
        /// <summary>
        /// Coverts the Danbooru array object to a list of BImage objects
        /// </summary>
        /// <param name="danbo"></param>
        /// <returns></returns>
        public static List<BImage> DanbooruToImages(this Danbooru[] danbo)
        {
            List<BImage> imgs = new List<BImage>();

            int i = 1;
            foreach (var d in danbo)
            {
                var tags = d.TagString.Split(' ');

                imgs.Add(new BImage(
                    d.Id.ToString(),
                    d.PreviewFileUrl,
                    d.FileUrl,
                    d.TagStringArtist.Split(' '),
                    tags,
                    d.FileExt,
                    d.Score
                ));
                i++;
            }

            return imgs;
        }

        /// <summary>
        /// Gets a Query object and parses it into a Danbooru-specific query string
        /// </summary>
        /// <param name="q"></param>
        /// <param name="url"></param>
        /// <returns></returns>
        public static string BuildDanbooru(this Query q, string url = "https://danbooru.donmai.us")
        {
            // Base endpoint
            string query = url+"/posts.json?tags=";

            // Tags
            query += q.Tags
                    .TrimEnd(' ')
                    .Replace(" ", "%20");

            // Rating
            string rating = "";

            if (q.Ratings.Contains(Rating.Safe))
                rating += "rating:s ";
            if (q.Ratings.Contains(Rating.Questionable))
                rating += "rating:q ";
            if (q.Ratings.Contains(Rating.Explicit))
                rating += "rating:e ";
            rating = rating.TrimEnd(' ').Replace(" ", "%20~");

            if (rating != "")
                rating = "%20" + rating;

            query += rating;

            //Prepare score query
            string score = "";

            if (q.MinScore != null && q.MaxScore != null)
            {
                score += q.MinScore;
                score += "..";
                score += q.MaxScore;
            }
            else
            {
                if (q.MinScore!= null)
                    score += q.MinScore;
                if (q.MaxScore != null)
                    score += q.MaxScore;
            }

            if (score != "")
                score = "%20score:" + score;

            query += score;

            // Add page number
            query += "&page=" + q.Page;
            
            // Add limit
            query += "&limit=30";

            return query;

        }
    }
}
